package SharedDrawing;

/*
 * This file is part of shared-drawing.
 * shared-drawing is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option )
 * any later version. shared-drawing is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * You should have received a copy of the GNU General Public License along with 
 * shared-drawing. If not, seehttp://www.gnu.org/licenses/.
 */

import common.XmlConstants;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.LocatorImpl;

/**
 * read incoming files
 * implements a SAX content handler
 */
public class XmlReader  implements ContentHandler
{
    //TODO : use the same style the server's parser one
    private Locator locator;   
    private Integer drawingId;
    private Integer pageId;
    private String  emitterId;
    private List<ShapeContent> toDraw;
    private ShapeContent currentShape;
    private boolean me;
    private boolean isAnUpDate;
    private SharedDrawingUI.UIWorker worker;
    
    public XmlReader() throws IOException
    {
        super();
        
        locator = new LocatorImpl();
        me = false;
        isAnUpDate = false;
        toDraw = new LinkedList();
        currentShape = null;
        worker = SharedDrawingUI.getInstance().getWorker();
    }



    @Override
    public void 
    startElement(String nameSpaceURI, String localName, String rawName, Attributes attributes) 
    throws SAXException
    {
        //always know if the emitter of a message is myself
        emitterId = attributes.getValue(XmlConstants.emitterId);
        if(emitterId != null)
        {
            if(ConnexionManager.getInstance().getUserId().equals(emitterId))
            {
                me = true;
            }
            else
            {
                me = false;
            }
        }
        //switch root element
        if(XmlConstants.createDrawing.equals(localName))
        {
            drawingId = Integer.parseInt(attributes.getValue(XmlConstants.drawingId));
            pageId = Integer.parseInt(attributes.getValue(XmlConstants.pageId));
            Pages.getInstance().setLastMessageId(drawingId, emitterId);
        }
        else if(XmlConstants.joinWorkgroup.equals(localName))
        {       
            String nickName = attributes.getValue(XmlConstants.emitterNickName);
            if(nickName == null ? 
                    ConnexionManager.getInstance().getNickname() == null : 
                    nickName.equals(ConnexionManager.getInstance().getNickname()))
            {
                ConnexionManager.getInstance().welcome(emitterId);
                worker.push(new Action(XmlConstants.welcome));
            }
            else
            {
                ConnexionManager.getInstance().someoneJoin(emitterId, nickName);
            }
        }
        else if(XmlConstants.leaveWorkgroup.equals(localName))
        { 
            if(me)
            {
                ConnexionManager.getInstance().goodBye();
            }
            else
            {
                ConnexionManager.getInstance().someoneLeave(emitterId);
            }
        }
        else if(XmlConstants.createPage.equals(localName))
        { 
            pageId = Integer.parseInt(attributes.getValue(XmlConstants.pageId));
            if(me)
            {
                Integer old = Integer.parseInt(attributes.getValue(XmlConstants.pageOld));
                Pages.getInstance().setPage(pageId, old);
            }
            else
            {
                String creator = attributes.getValue(XmlConstants.creatorId);
                if(creator == null)
                {
                    creator = emitterId;
                }
                String name = attributes.getValue(XmlConstants.pageName);
                Pages.getInstance().createPageFromUser(pageId, name, creator);
            }
        }
        else if(XmlConstants.openPage.equals(localName))
        { 
            if(!me)
            {
                pageId = Integer.parseInt(attributes.getValue(XmlConstants.pageId));
                String viewer = attributes.getValue(XmlConstants.viewerId);
                Pages.getInstance().incPageView(pageId, viewer);
            }
        }
        else if(XmlConstants.closePage.equals(localName))
        { 
            if(!me)
            {
                pageId = Integer.parseInt(attributes.getValue(XmlConstants.pageId));
                Pages.getInstance().decPageView(pageId, emitterId);
            }
        }
        else if(XmlConstants.chat.equals(localName))
        { 
            if(!me)
            {
                Chat.getInstance().append(emitterId, attributes.getValue(XmlConstants.message));
            }
        }
        else if(XmlConstants.wgContent.equals(localName))
        { 
            if(!me)
            {
                WgContent wgContent = new WgContent(attributes.getValue(XmlConstants.wgContentType));
                for(int index = 0;index<attributes.getLength();index++)
                {
                    String current = attributes.getLocalName(index);
                    if(!XmlConstants.wgContentType.equals(current))
                        wgContent.addContent(current, attributes.getValue(index));
                }
                currentShape.addElement(wgContent);
            }
        }
        else if(XmlConstants.shapeContent.equals(localName))
        { 
            currentShape = new ShapeContent();
            WgContent wgContent = new WgContent(attributes.getValue(XmlConstants.shapeContentType));
            for(int index = 0;index<attributes.getLength();index++)
            {
                String current = attributes.getLocalName(index);
                if(!XmlConstants.shapeContentType.equals(current))
                    wgContent.addContent(current, attributes.getValue(index));
            }
            currentShape.setBoundingBox(wgContent);
            toDraw.add(currentShape);
            if(me)
            {
                if(attributes.getValue(XmlConstants.shapeContentReferenceId) == null)
                {
                    Pages.getInstance().refactorShapeId(pageId,
                        Long.parseLong(attributes.getValue(XmlConstants.shapeContentId)),
                        Long.parseLong(attributes.getValue(XmlConstants.shapeContentOldId)));
                }
            }
        }
        else if(XmlConstants.upToDate.equals(localName))
        { 
            isAnUpDate = true;
        }
        else if(XmlConstants.askUpToDate.equals(localName))
        {
            XmlGenerator.sendXml(emitterId);
        }
        else if(XmlConstants.error.equals(localName))
        { 
            Action action = new Action(XmlConstants.error);
            action.addContent(XmlConstants.message, 
                    attributes.getValue(XmlConstants.message));
            SharedDrawingUI.getInstance().getWorker().push(action);
        }
        else if(XmlConstants.connect.equals(localName))
        {
            Action action = new Action(XmlConstants.connect);
            SharedDrawingUI.getInstance().getWorker().push(action);
        }
        else if(XmlConstants.connectRefused.equals(localName))
        {
            Action action = new Action(XmlConstants.connectRefused);
            action.addContent(XmlConstants.message, attributes.getValue(XmlConstants.message));
            SharedDrawingUI.getInstance().getWorker().push(action);
        }
        else
        {
            System.out.println("Invalid message received : "+localName);
        }
    }
    
    @Override
    public void endElement(String nameSpaceURI, String localName, String rawName) throws SAXException{
        if(XmlConstants.createDrawing.equals(localName) && (!me))
        {
            Pages.getInstance().draw(pageId, toDraw);
            toDraw.clear();
        }
        else if(XmlConstants.pageCollection.equals(localName))
        {
            Pages.getInstance().clearViewers();
        }
    }
    
    @Override
    public void startDocument() throws SAXException {   
        drawingId = 0;
        emitterId = "0";
        toDraw.clear();
        currentShape = null;
        isAnUpDate = false;
    }
    
    @Override
    public void setDocumentLocator(Locator value) {
        locator =  value;
    }

    @Override
    public void endDocument() throws SAXException {
    }
    @Override
    public void startPrefixMapping(String prefix, String URI) throws SAXException{
    }
    @Override
    public void endPrefixMapping(String prefix) throws SAXException{
    }
    @Override
    public void characters(char[] ch, int start, int end) throws SAXException{   
    }
    @Override
    public void ignorableWhitespace(char[] ch, int start, int end) throws SAXException{
    }
    @Override
    public void processingInstruction(String target, String data) throws SAXException{  
    }
    @Override
    public void skippedEntity(String arg0) throws SAXException{    
    }

}
